import React, { useState, useEffect, useRef, memo } from 'react';
import './index.scss'
import { VerticalRightOutlined, CaretRightOutlined, PauseOutlined, VerticalLeftOutlined, SoundFilled, MutedFilled } from '@ant-design/icons';
import { message, Slider, Tooltip } from 'antd';
import { formateTime } from '../../utils';
import { useAppDispatch, useAppSelector } from '../../utils/storeHook/storeHook';
import { setActCurTime, setActMusicInfo, setMusicMode } from '../../store/modules/musicStore';
import http from '../../utils/http';
import api from '../../api';
import PlayList from './components/PlayList';

const musicToken = import.meta.env.VITE_YUN_MUSIC_TOKEN
const cookie = import.meta.env.VITE_YUN_MUSIC_COOKIE

const MusicPlayer = memo(() => {
    const [messageApi, contextHolder] = message.useMessage();

    const detail = useAppSelector(state=>state.music.actMusicInfo)
    const mode = useAppSelector(state=>state.music.musicMode)
    const playList = useAppSelector(state=>state.music.playList)
    const dispatch = useAppDispatch()

    const [isPlaying, setIsPlaying] = useState(false);
    const [duration, setDuration] = useState<number>(0)
    const [currentTime, setCurrentTime] = useState<string>('--:--');
    const [progress, setProgress] = useState(0);
    const [isMuted, setIsMuted] = useState(false);
    const [volume, setVolume] = useState<number>();
    const [showPlayList, setShowPlayList] = useState(false);
    const [curLyricList, setCurLyricList] = useState<{[key: number]:string}|null>(null)
    const [curLyric, setCurLyri] = useState<string>('');

    const videoRef = useRef<HTMLAudioElement>(null);
    const progressRef = useRef<HTMLDivElement>(null);
    const progressBarRef = useRef<HTMLDivElement>(null);
    const dragingTipRef = useRef<HTMLDivElement>(null);
    const volumnSliderRef = useRef<HTMLDivElement>(null);
    const drapLeftTimer = useRef<NodeJS.Timeout | null>(null);
    const volumnDrapLeftTimer = useRef<NodeJS.Timeout | null>(null);
    const timeTimer = useRef<NodeJS.Timeout | null>(null);

    const progressStateRef = useRef({
        isDragging: false,
        start: 0,
        end: 0,
    })

    async function getMusicUrl(id:string|number){
        const detailRes = await http.post(api.music.getMusicDetail,{token:musicToken,id:id})
        const urlRes = await http.post(api.music.getMusicUrl,{token:musicToken,id:id,cookie:cookie})
        const musicInfo = {
            id:detailRes.data.songs[0].id,
            name:detailRes.data.songs[0].name,
            artist:detailRes.data.songs[0].ar.map((item:any)=>item.name).join('/'),
            coverUrl:detailRes.data.songs[0].al.picUrl,
            time:detailRes.data.songs[0].dt,
            url:urlRes.data.url
        }
        dispatch(setActMusicInfo(musicInfo))
    }

    async function getMusicLyric(){
        if(!detail) return
        try{
            const res = await http.post(api.music.getMusicLyric,{token:musicToken,id:detail.id})
            const lyricArr = res.data.lyric.split('\n')
            const lyricObj:{[key:string]:string} = {}
            lyricArr.forEach((item:string)=>{
                const match = item.match(/^\[(\d{2}):(\d{2})\.(\d{1,4})\]\s*(.*)$/)
                if(match){
                    
                    const [,min,sec,ms,text] = match
                    const time = parseInt(min)*60*1000 + parseInt(sec)*1000 + parseInt(ms)
                    lyricObj[time] = text
                }
            })
            setCurLyricList(lyricObj)
            
        }catch(err){
            console.log(err);
        }
    }

    function onLoaded(e:React.SyntheticEvent<HTMLAudioElement>){
        if(!videoRef.current) return
        videoRef.current.currentTime = 0
        getMusicLyric()
        setCurrentTime('00:00')
        
        setProgress(0)
        setDuration(e.currentTarget.duration*1000)
        // if(detail?.curTime){
        //     if(!videoRef.current) return
        //     videoRef.current.currentTime = detail.curTime/1000
        // }
    }

    function handleEnded() {
        if(!detail) return
        if(playList.length == 0) return messageApi.info('播放列表为空')
        dispatch(setActCurTime(0))
        if(mode == 3){
            videoRef.current&&(videoRef.current.currentTime = 0)
            play()
        }else if(mode == 2){ 
            getMusicUrl(playList[Math.floor(Math.random()*playList.length)].id)
        }else if(mode == 1){
            const index = playList.findIndex(item=>item.id == detail.id)
            if(index == playList.length-1){
                getMusicUrl(playList[0].id)
            }else if(index>=0){
                getMusicUrl(playList[index+1].id)
            }else{
                getMusicUrl(playList[0].id)
            }
        }
    }

    function togglePlayingState(){
        isPlaying?pause():play()
    }

    function pause() {
        if(!videoRef.current) return
        videoRef.current.pause();
        setIsPlaying(false);
    }

    function play() {
        if(!videoRef.current) return
        videoRef.current.play().catch((err)=>{
            console.error(err);
            setIsPlaying(false)
            return
        });
        setIsPlaying(true);
    }

    function findCurLyric(time:number,lyric:{[key:number]:string}){
        const times = Object.keys(lyric)

        for(let i = 0; i < times.length; i++){
            if((time+200) >= (+times[i])){
                setCurLyri(lyric[+times[i]])
            }else{
                break
            }
        }
    }

    function onTimeUpdate(e:React.SyntheticEvent<HTMLAudioElement, Event>){
        const curTime = e.currentTarget.currentTime * 1000
        const duration = e.currentTarget.duration * 1000
        if(curLyricList){
            findCurLyric(curTime,curLyricList)
        }
        setCurrentTime(formateTime(curTime))
        setProgress(curTime/duration*100)
        if(timeTimer.current) return
        timeTimer.current = setTimeout(()=>{
            dispatch(setActCurTime(curTime))
            timeTimer.current = null
        },2000)
    }

    function handleNext(){
        if(!detail) return
        if(playList.length == 0) return messageApi.info('播放列表为空')
        if(mode == 3){
            videoRef.current&&(videoRef.current.currentTime = 0)
        }else if(mode == 2){ 
            getMusicUrl(playList[Math.floor(Math.random()*playList.length)].id)
        }else if(mode == 1){
            const index = playList.findIndex(item=>item.id == detail.id)
            if(index == playList.length-1){
                getMusicUrl(playList[0].id)
            }else if(index>=0){
                getMusicUrl(playList[index+1].id)
            }else{
                getMusicUrl(playList[0].id)
            }
        }
    }

    function handlePrev(){
        if(!detail) return
        if(playList.length == 0) return messageApi.info('播放列表为空')
        const index = playList.findIndex(item=>item.id == detail.id)
        if(index == 0){
            getMusicUrl(playList[playList.length-1].id)
        }else{
            getMusicUrl(playList[index-1].id)
        }
    }

    function handleMouseDown(e:React.MouseEvent<HTMLDivElement, MouseEvent>){
        if(!progressRef.current) return;
        progressStateRef.current.isDragging = true
        const rect = progressRef.current.getBoundingClientRect()
        progressStateRef.current.start = (e.clientX - rect.left)/rect.width
        progressStateRef.current.end = (e.clientX - rect.left)/rect.width
    }

    // 鼠标在控制器移动
    function handleMouseMove(e:React.MouseEvent<HTMLDivElement, MouseEvent>){
        if(!progressRef.current || !progressBarRef.current) return;
        if(!progressStateRef.current.isDragging) return;
        const rect = progressRef.current.getBoundingClientRect()
        progressStateRef.current.end = (e.clientX - rect.left)/rect.width
        progressBarRef.current.style.width = `${(e.clientX - rect.left)/rect.width * 100}%`
        if(dragingTipRef.current){
            dragingTipRef.current.style.left = e.clientX + 'px'
            dragingTipRef.current.style.top = rect.top - 50 + 'px'
            dragingTipRef.current.style.display = 'flex'
        }
        // 其他隐藏
        soundLeave(500)
    }

    function handleMouseUp(){
        if(!videoRef.current || !detail?.time) return
        if(!progressStateRef.current.isDragging) return;
        videoRef.current.currentTime = progressStateRef.current.end * detail.time / 1000
        progressStateRef.current.isDragging = false
    }

    function handleMouseLeave(){
        drapLeftTimer.current = setTimeout(() => {
            progressStateRef.current.isDragging = false
        }, 3000);
    }

    function handleMouseEnter(){
        if(drapLeftTimer.current){
            clearTimeout(drapLeftTimer.current)
        }
    }

    function toggleMuted(){
        if(!videoRef.current) return
        videoRef.current.muted = !isMuted
        setIsMuted(!isMuted)
    }

    function soundEnter(){
        if(volumnDrapLeftTimer.current) clearTimeout(volumnDrapLeftTimer.current)
        if(!volumnSliderRef.current) return
        volumnSliderRef.current.style.width = '80px'
    }
    function soundLeave(time:number){
        volumnDrapLeftTimer.current = setTimeout(()=>{
            if(!volumnSliderRef.current) return
            volumnSliderRef.current.style.width = '0'
        }, time)
    }

    function handleVolumnChange(value: number){
        setVolume(value/100)
        if(Math.floor(value) == 0){
            setIsMuted(true)
        }else{
            setIsMuted(false)
        }
    }

    function handleChangeMode(){
        console.log(mode);
        if(mode === 1){
            dispatch(setMusicMode(2))
        }else if(mode === 2){
            dispatch(setMusicMode(3))
        }else if(mode === 3){
            dispatch(setMusicMode(1))
        }else{
            dispatch(setMusicMode(1))
        }
    }

    useEffect(()=>{
        if(!videoRef.current || !volume) return
        videoRef.current.volume = volume
        localStorage.setItem('volume', volume.toString())
    },[volume])

    useEffect(() => { 
        play()
    }, [detail?.id]);

    useEffect(() => { 
        if(!progressBarRef.current || progressStateRef.current.isDragging) return
        progressBarRef.current.style.width = `${progress}%`
    }, [currentTime]);

    useEffect(()=>{
        if(progressStateRef.current.isDragging == false){
            if(dragingTipRef.current){
                dragingTipRef.current.style.display = 'none'
            }
        }
    },[progressStateRef.current.isDragging])

    useEffect(() => {
        const lcVolumn = localStorage.getItem('volume')
        const localVolumn = lcVolumn? +JSON.parse(lcVolumn): 0.7
        setVolume(+localVolumn)
        return ()=>{
            setIsPlaying(false)
            pause()
        }
    }, []);
    return (
        <>
            {contextHolder}
            <div className='musicPlayer_dragingTip' ref={dragingTipRef} onMouseLeave={(e)=>e.currentTarget.style.display = 'none'}>
                {formateTime(progressStateRef.current.end * duration)}
            </div>
            <div className='musicPlayer_box'>
                <audio 
                    onEnded={handleEnded} 
                    src={detail?.url} 
                    ref={videoRef} 
                    onTimeUpdate={(e)=>onTimeUpdate(e)}
                    onLoadedData={onLoaded}
                    autoPlay={isPlaying}
                ></audio>
                <div 
                    className='musicPlayer_box_controls' 
                    onMouseUp={handleMouseUp}
                    onMouseMove={handleMouseMove}
                    onMouseLeave={handleMouseLeave}
                    onMouseEnter={handleMouseEnter}
                >
                    <div className="musicPlayer_info">
                        <div className="musicPlayer_cover">
                            {(detail&&detail.coverUrl)?<img src={detail.coverUrl} alt="" />:
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" filter="none">
                                
                                <g>
                                <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z" fill="currentColor"></path>
                                </g>
                            </svg>}
                        </div>
                        <div className="musicPlayer_details">
                            <div className="musicPlayer_title">
                                <Tooltip placement="top" title={(detail&&detail.name)&&detail.name}>
                                    {(detail&&detail.name)&&detail.name}
                                </Tooltip>
                            </div>
                            <div className="musicPlayer_artist">
                                <Tooltip placement="top" title={(detail&&detail.artist)&&detail.artist}>

                                    {(detail&&detail.artist)&&detail.artist}
                                </Tooltip>
                            </div>
                        </div>
                    </div>
                    <div className='musicPlayer_actions'>
                        <div className="musicPlayer_action prev" onClick={handlePrev}>
                            <VerticalRightOutlined />
                        </div>
                        <div className="musicPlayer_action play" onClick={togglePlayingState}>
                            {isPlaying==true?<PauseOutlined />:<CaretRightOutlined />}
                        </div>
                        <div className="musicPlayer_action next" onClick={handleNext}>
                            <VerticalLeftOutlined />
                        </div>
                        <div className='musicPlayer_action mode' onClick={handleChangeMode}>
                            {mode==1&&<Tooltip title="顺序播放">
                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="1em" height="1em" filter="none">
                                    
                                    <g>
                                    <path d="M8 5.333h20c0.736 0 1.333 0.597 1.333 1.333v0 9.333h-2.667v-8h-18.667v4l-6.667-5.333 6.667-5.333v4zM24 26.667h-20c-0.736 0-1.333-0.597-1.333-1.333v0-9.333h2.667v8h18.667v-4l6.667 5.333-6.667 5.333v-4z" fill="currentColor"></path>
                                    </g>
                                </svg>
                            </Tooltip>}
                            {mode==2&&<Tooltip title="随机播放">
                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="1em" height="1em" filter="none">
                                    <g>
                                    <path d="M24 23.844v-2.511l6.667 4-6.667 4v-2.787c-4.215-0.62-7.673-3.356-9.299-7.076l-0.030-0.077-0.004-0.007-0.004 0.008c-1.883 4.313-6.111 7.272-11.029 7.272h-0.967v-2.667h0.967c3.826-0 7.114-2.302 8.555-5.597l0.023-0.060 1.004-2.343-1.004-2.343c-1.464-3.355-4.753-5.657-8.579-5.657h-0.967v-2.667h0.967c4.919 0 9.147 2.96 10.999 7.196l0.030 0.077 0.004 0.007 0.004-0.008c1.657-3.797 5.115-6.532 9.264-7.144l0.065-0.008v-2.787l6.667 4-6.667 4v-2.511c-3.114 0.592-5.641 2.664-6.855 5.441l-0.023 0.060-1.004 2.343 1.004 2.343c1.238 2.837 3.765 4.91 6.82 5.492l0.058 0.009z" fill="currentColor"></path>
                                    </g>
                                </svg>
                            </Tooltip>}
                            {mode==3&&<Tooltip title="单曲循环">
                                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="1em" height="1em" filter="none">
                                        <g>
                                        <path d="M10.667 26.667v2.576c0 0 0 0.001 0 0.001 0 0.368-0.298 0.667-0.667 0.667-0.163 0-0.312-0.058-0.428-0.155l0.001 0.001-5.493-4.577c-0.147-0.123-0.24-0.307-0.24-0.512 0-0.368 0.298-0.667 0.667-0.667 0.001 0 0.002 0 0.003 0h19.491c1.473 0 2.667-1.194 2.667-2.667v0-10.667h2.667v10.667c0 2.946-2.388 5.333-5.333 5.333v0h-13.333zM21.333 5.333v-2.576c0-0 0-0.001 0-0.001 0-0.368 0.298-0.667 0.667-0.667 0.163 0 0.312 0.058 0.428 0.155l-0.001-0.001 5.493 4.577c0.147 0.123 0.24 0.307 0.24 0.512 0 0.368-0.298 0.667-0.667 0.667-0 0-0.001 0-0.001 0h-19.492c-1.473 0-2.667 1.194-2.667 2.667v0 10.667h-2.667v-10.667c0-2.946 2.388-5.333 5.333-5.333v0h13.333zM14.667 10.667h2.667v10.667h-2.667v-8h-2.667v-1.333l2.667-1.333z" fill="currentColor"></path>
                                        </g>
                                </svg>
                            </Tooltip>}
                        </div>
                        <div 
                            className='volumn' 
                            onMouseMove={soundEnter}
                            onMouseLeave={()=>soundLeave(500)}
                        >
                            <div className='musicPlayer_volumn_icon' onClick={toggleMuted}>{isMuted?<MutedFilled />:<SoundFilled />}</div>
                            <div 
                                className='musicPlayer_volumn_slider_box'
                                ref={volumnSliderRef}
                            >
                                <div 
                                    className='musicPlayer_volumn_slider' 
                                    onClick={(e)=>e.stopPropagation()}
                                    onMouseMove={soundEnter}
                                    onMouseLeave={()=>soundLeave(500)}
                                >
                                    <Slider 
                                        value={(volume as number)*100}
                                        min={0} 
                                        max={100} 
                                        onChange={handleVolumnChange} 
                                    />
                                </div>
                                <span className='musicPlayer_volumn_value'>{(volume&&volume*100)?.toFixed(0)}</span>
                            </div>
                        </div>
                    </div>
                    <div className='musicPlayer_progress_box'>
                        <div 
                            className='musicPlayer_progress'
                            ref={progressRef}
                            onMouseDown={handleMouseDown}
                        >
                            <div className='musicPlayer_progress_bar' ref={progressBarRef}>
                            </div>
                        </div>
                        <span className='musicPlayer_progress_time'>
                            {`${currentTime}/${formateTime(duration)}`}
                        </span>
                    </div>
                    {curLyric&&<div className='musicPlayer_lyrics'>
                        {curLyric}
                    </div>}
                    <Tooltip title='播放列表'>
                        <div className='musicPlayer_playList' onClick={()=>setShowPlayList(!showPlayList)}>
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="1em" height="1em" filter="none">
                                <g>
                                <path d="M24 19H40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path><path d="M24 10H40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path><path d="M8 38H40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path><path d="M8 28H40" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" fill="none"></path><path d="M8 10L16 15L8 20V10Z" fill="none" stroke="currentColor" stroke-width="4" stroke-linejoin="round"></path>
                                </g>
                            </svg>
                        </div>
                    </Tooltip>
                </div>
            </div>
            <PlayList visible={showPlayList} onClose={()=>setShowPlayList(false)}></PlayList>
        </>
    )
});

export default MusicPlayer;
